package io.kiki.sba.registry.task;


import io.kiki.sba.registry.metrics.TaskMetrics;
import io.kiki.sba.registry.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;


public class MetricsableThreadPoolExecutor extends ThreadPoolExecutor {
    private static final Logger logger = LoggerFactory.getLogger(MetricsableThreadPoolExecutor.class);

    protected final String executorName;

    public MetricsableThreadPoolExecutor(String executorName, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
        this.executorName = executorName;
        registerTaskMetrics();
        this.setRejectedExecutionHandler(handler);
    }

    public MetricsableThreadPoolExecutor(String executorName, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        this(executorName, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, new RejectedLogErrorHandler(true));
    }

    public static MetricsableThreadPoolExecutor newExecutor(String executorName, int corePoolSize, int size, RejectedExecutionHandler handler) {
        return new MetricsableThreadPoolExecutor(executorName, corePoolSize, corePoolSize, 60, TimeUnit.SECONDS, size <= 1024 * 4 ? new ArrayBlockingQueue<>(size) : new LinkedBlockingQueue<>(size), new NamedThreadFactory(executorName, true), handler);
    }

    public static MetricsableThreadPoolExecutor newExecutor(String executorName, int corePoolSize, int size) {
        return newExecutor(executorName, corePoolSize, size, new RejectedLogErrorHandler(true));
    }

    private void registerTaskMetrics() {
        TaskMetrics.getInstance().registerThreadExecutor(executorName, this);
    }

}
